<!DOCTYPE html>
<html lang="cn-ZH">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Rust入门（十六）：手写web服务器和线程池 | 摸鱼老萌新</title>
    <meta name="description" content="Front end project and tips sharing">
    <link rel="stylesheet" href="/assets/style.8f1fef60.css">
    <link rel="modulepreload" href="/assets/app.75d9ecf2.js">
    <link rel="modulepreload" href="/assets/articles_rust_16.手写web服务器和线程池.md.97f59e40.lean.js">
    
    <script id="check-dark-light">(()=>{const e=localStorage.getItem("vitepress-theme-appearance"),a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
  </head>
  <body>
    <div id="app"><div class="Layout" data-v-c6a644e1><!--[--><!--]--><!--[--><span tabindex="-1" data-v-151f2593></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-151f2593> Skip to content </a><!--]--><!----><header class="VPNav" data-v-c6a644e1 data-v-a71a30f1><div class="VPNavBar has-sidebar" data-v-a71a30f1 data-v-6f1d18b5><div class="container" data-v-6f1d18b5><div class="VPNavBarTitle has-sidebar" data-v-6f1d18b5 data-v-d5925166><a class="title" href="/" data-v-d5925166><!--[--><!--]--><!--[--><img class="VPImage logo" src="/logo.jpg" data-v-e13a1912><!--]--><!--[-->摸鱼老萌新<!--]--><!--[--><!--]--></a></div><div class="content" data-v-6f1d18b5><!--[--><!--]--><!----><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-6f1d18b5 data-v-f83db6ba><span id="main-nav-aria-label" class="visually-hidden" data-v-f83db6ba>Main Navigation</span><!--[--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-f83db6ba data-v-6ffb57d3><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-6ffb57d3><span class="text" data-v-6ffb57d3><!----> 前端 <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-6ffb57d3><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-6ffb57d3><div class="VPMenu" data-v-6ffb57d3 data-v-1c5d0cfc><div class="items" data-v-1c5d0cfc><!--[--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/basic/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->基础<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/vue/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->Vue<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/react/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->React<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/mini/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->小程序<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/electron/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->Electron<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/web3d/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->Web3D<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/rust/01.%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8.html" data-v-e8e0fb1d data-v-3c355974><!--[-->Rust<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/other/vitepress/01.vitepress%E7%9A%84%E6%90%AD%E5%BB%BA.html" data-v-e8e0fb1d data-v-3c355974><!--[-->其他<!--]--><!----></a></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/leetcode/LEET_CODE%E9%A2%98%E8%A7%A3/47.%20%E5%85%A8%E6%8E%92%E5%88%97%20II.html" data-v-f83db6ba data-v-47a2263e data-v-3c355974><!--[-->算法<!--]--><!----></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/intent/" data-v-f83db6ba data-v-47a2263e data-v-3c355974><!--[-->项目<!--]--><!----></a><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-6f1d18b5 data-v-a3e7452b><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-label="toggle dark mode" aria-checked="false" data-v-a3e7452b data-v-1899cd41 data-v-086e8519><span class="check" data-v-086e8519><span class="icon" data-v-086e8519><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-1899cd41><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-1899cd41><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-6f1d18b5 data-v-738bef5a data-v-f6988cfb><!--[--><a class="VPSocialLink" href="https://github.com/aiai0603" target="_blank" rel="noopener" data-v-f6988cfb data-v-e57698f6><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-6f1d18b5 data-v-e89b88d7 data-v-6ffb57d3><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-6ffb57d3><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="icon" data-v-6ffb57d3><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle><circle cx="5" cy="12" r="2"></circle></svg></button><div class="menu" data-v-6ffb57d3><div class="VPMenu" data-v-6ffb57d3 data-v-1c5d0cfc><!----><!--[--><!--[--><!----><div class="group" data-v-e89b88d7><div class="item appearance" data-v-e89b88d7><p class="label" data-v-e89b88d7>Appearance</p><div class="appearance-action" data-v-e89b88d7><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-label="toggle dark mode" aria-checked="false" data-v-e89b88d7 data-v-1899cd41 data-v-086e8519><span class="check" data-v-086e8519><span class="icon" data-v-086e8519><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-1899cd41><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-1899cd41><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div></div></div><div class="group" data-v-e89b88d7><div class="item social-links" data-v-e89b88d7><div class="VPSocialLinks social-links-list" data-v-e89b88d7 data-v-f6988cfb><!--[--><a class="VPSocialLink" href="https://github.com/aiai0603" target="_blank" rel="noopener" data-v-f6988cfb data-v-e57698f6><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-6f1d18b5 data-v-e5dd9c1c><span class="container" data-v-e5dd9c1c><span class="top" data-v-e5dd9c1c></span><span class="middle" data-v-e5dd9c1c></span><span class="bottom" data-v-e5dd9c1c></span></span></button></div></div></div><!----></header><div class="VPLocalNav" data-v-c6a644e1 data-v-aac27d5e><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-aac27d5e><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="menu-icon" data-v-aac27d5e><path d="M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"></path><path d="M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"></path><path d="M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"></path><path d="M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"></path></svg><span class="menu-text" data-v-aac27d5e>Menu</span></button><a class="top-link" href="#" data-v-aac27d5e> Return to top </a></div><aside class="VPSidebar" data-v-c6a644e1 data-v-f332cb62><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-f332cb62><span class="visually-hidden" id="sidebar-aria-label" data-v-f332cb62> Sidebar Navigation </span><!--[--><div class="group" data-v-f332cb62><section class="VPSidebarGroup collapsible" data-v-f332cb62 data-v-2976c796><div class="title" role="button" data-v-2976c796><h2 class="title-text" data-v-2976c796>rust</h2><div class="action" data-v-2976c796><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 24 24" class="icon minus" data-v-2976c796><path d="M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2zM20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"></path><path d="M16,11H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h8c0.6,0,1-0.4,1-1S16.6,11,16,11z"></path></svg><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon plus" data-v-2976c796><path d="M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2z M20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"></path><path d="M16,11h-3V8c0-0.6-0.4-1-1-1s-1,0.4-1,1v3H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h3v3c0,0.6,0.4,1,1,1s1-0.4,1-1v-3h3c0.6,0,1-0.4,1-1S16.6,11,16,11z"></path></svg></div></div><div class="items" data-v-2976c796><!--[--><!--[--><a class="VPLink link link" href="/articles/rust/01.%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>01.基础入门</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/02.%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>02.基础语法</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/03.%E6%8C%87%E9%92%88%E4%B8%8E%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>03.指针与内存分配</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/04.%E7%A8%8B%E5%BA%8F%E7%BB%93%E6%9E%84%E5%92%8C%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>04.程序结构和异常处理</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/05.%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E6%B3%9B%E5%9E%8B.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>05.数据结构与泛型</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/06.trait%E4%B8%8E%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>06.trait与生命周期</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/07.%E7%BC%96%E5%86%99%E6%B5%8B%E8%AF%95.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>07.编写测试</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/08.%E6%9E%84%E5%BB%BA%E5%91%BD%E4%BB%A4%E8%A1%8C%E7%A8%8B%E5%BA%8F.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>08.构建命令行程序</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/09.%E9%97%AD%E5%8C%85%E4%B8%8E%E8%BF%AD%E4%BB%A3%E5%99%A8.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>09.闭包与迭代器</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/10.%E5%8F%91%E5%B8%83%E9%A1%B9%E7%9B%AE.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>10.发布项目</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/11.%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>11.智能指针</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/12.%E5%B9%B6%E5%8F%91.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>12.并发</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/13.%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>13.面向对象</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/14.%E4%B8%8D%E5%AE%89%E5%85%A8Rust.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>14.不安全Rust</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/15.%E9%AB%98%E7%BA%A7%E7%89%B9%E6%80%A7.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>15.高级特性</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link active" href="/articles/rust/16.%E6%89%8B%E5%86%99web%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%92%8C%E7%BA%BF%E7%A8%8B%E6%B1%A0.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>16.手写web服务器和线程池</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/17.rust%E5%BC%82%E6%AD%A5%E7%BC%96%E7%A8%8B.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>17.rust异步编程</span><!--]--><!----></a><!----><!--]--><!--]--></div></section></div><div class="group" data-v-f332cb62><section class="VPSidebarGroup collapsible collapsed" data-v-f332cb62 data-v-2976c796><div class="title" role="button" data-v-2976c796><h2 class="title-text" data-v-2976c796>rustweb</h2><div class="action" data-v-2976c796><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 24 24" class="icon minus" data-v-2976c796><path d="M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2zM20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"></path><path d="M16,11H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h8c0.6,0,1-0.4,1-1S16.6,11,16,11z"></path></svg><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon plus" data-v-2976c796><path d="M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2z M20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"></path><path d="M16,11h-3V8c0-0.6-0.4-1-1-1s-1,0.4-1,1v3H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h3v3c0,0.6,0.4,1,1,1s1-0.4,1-1v-3h3c0.6,0,1-0.4,1-1S16.6,11,16,11z"></path></svg></div></div><div class="items" data-v-2976c796><!--[--><!--[--><a class="VPLink link link" href="/articles/rustweb/01.%E7%AE%80%E5%8D%95%20server.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>01.简单 server</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/02.Actix.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>02.Actix</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/03.%E8%BF%9E%E6%8E%A5%E6%95%B0%E6%8D%AE%E5%BA%93.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>03.连接数据库</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/04.%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>04.错误处理</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/05.%E5%AE%8C%E6%95%B4%E9%A1%B9%E7%9B%AE%E9%87%8D%E6%9E%84.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>05.完整项目重构</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/06.%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AFweb%E5%BA%94%E7%94%A8.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>06.服务器端web应用</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/07.WebAssembly.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>07.WebAssembly</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/08.%E5%8F%91%E5%B8%83.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>08.发布</span><!--]--><!----></a><!----><!--]--><!--]--></div></section></div><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-c6a644e1 data-v-c95df128><div class="VPDoc has-sidebar has-aside" data-v-c95df128 data-v-37ebe389><div class="container" data-v-37ebe389><div class="aside" data-v-37ebe389><div class="aside-curtain" data-v-37ebe389></div><div class="aside-container" data-v-37ebe389><div class="aside-content" data-v-37ebe389><div class="VPDocAside" data-v-37ebe389 data-v-afc4c1a1><!--[--><!--]--><!--[--><!--]--><div class="VPDocAsideOutline" data-v-afc4c1a1 data-v-2865c0b0><div class="content" data-v-2865c0b0><div class="outline-marker" data-v-2865c0b0></div><div class="outline-title" data-v-2865c0b0>On this page</div><nav aria-labelledby="doc-outline-aria-label" data-v-2865c0b0><span class="visually-hidden" id="doc-outline-aria-label" data-v-2865c0b0> Table of Contents for current page </span><ul class="root" data-v-2865c0b0 data-v-1188541a><!--[--><!--]--></ul></nav></div></div><!--[--><!--]--><div class="spacer" data-v-afc4c1a1></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-37ebe389><div class="content-container" data-v-37ebe389><!--[--><!--]--><main class="main" data-v-37ebe389><div style="position:relative;" class="vp-doc _articles_rust_16_%E6%89%8B%E5%86%99web%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%92%8C%E7%BA%BF%E7%A8%8B%E6%B1%A0" data-v-37ebe389><div><h1 id="rust入门（十六）：手写web服务器和线程池" tabindex="-1">Rust入门（十六）：手写web服务器和线程池 <a class="header-anchor" href="#rust入门（十六）：手写web服务器和线程池" aria-hidden="true">#</a></h1><p>这一章将实现一个手写的 web server 和 多线程的服务器，用到之前学到的所有特性</p><h2 id="简单的web-server" tabindex="-1">简单的web server <a class="header-anchor" href="#简单的web-server" aria-hidden="true">#</a></h2><p>作为一个 web 服务器，我们首先要能接收到请求，目前市面上的 web 服务大多数都是基于 HTTP 和 HTTPS 协议的，而他们有是基于 TCP 协议传输的 ，所以我们希望我们的服务器可以监听 TCP 连接，rust 的库函数中提供了 <code>TcpListener</code> 这样的函数来监听 TCP 连接，我们新建一个项目，然后在 <code>src/main.rs</code> 中编写监听功能。</p><p><code>TcpListener</code> 的 <code>incoming</code> 方法返回一个迭代器，它提供了一系列的流，<strong>流</strong>（<em>stream</em>）代表一个客户端和服务端之间打开的连接</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">net</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">TcpListener</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> listener </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">TcpListener</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">bind</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">127.0.0.1:7878</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> stream </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> listener</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">incoming</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> stream </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Connection established!</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>运行代码，之后访问 <strong>127.0.0.1:7878</strong> 就可以看到接收到了信息，如果你成功接收到了信息，那么下一步就是怎么样处理信息，我们使用一个缓冲区接收我们的数据，此时它是一个 &amp;u8 类型的字节流数据，我们将它转化为字符串打印出来：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::{</span></span>
<span class="line"><span style="color:#FFCB6B;">    io</span><span style="color:#89DDFF;">::{</span><span style="color:#FFCB6B;">prelude</span><span style="color:#89DDFF;">::*,</span><span style="color:#FFCB6B;"> BufReader</span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#FFCB6B;">    net</span><span style="color:#89DDFF;">::{</span><span style="color:#FFCB6B;">TcpListener</span><span style="color:#89DDFF;">,</span><span style="color:#FFCB6B;"> TcpStream</span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> listener </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">TcpListener</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">bind</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">127.0.0.1:7878</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> stream </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> listener</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">incoming</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> stream </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#82AAFF;">handle_connection</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">stream</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">handle_connection</span><span style="color:#89DDFF;">(</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> stream</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">TcpStream</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> buffer </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1024</span><span style="color:#89DDFF;">];</span></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">read</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> buffer</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Request: </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">String</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">from_utf8_lossy</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">buffer</span><span style="color:#89DDFF;">[..]));</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>现在运行我们的程序，它将打印出一个完整的 TCP 请求，作为一个服务器，对于一个请求，我们需要做出我们的回复，提供给它需要的资源，这里我们就返回先尝试返回一个简单的响应：</p><p>因为 <code>stream</code> 的 <code>write_all</code> 方法获取一个 <code>&amp;[u8]</code> 并直接将这些字节发送给连接。所以我们调用<code>as_bytes</code> 对数据进行转化</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">handle_connection</span><span style="color:#89DDFF;">(</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> stream</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">TcpStream</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> buffer </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1024</span><span style="color:#89DDFF;">];</span></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">read</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> buffer</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> response </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">HTTP/1.1 200 OK</span><span style="color:#A6ACCD;">\r\n\r\n</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">write_all</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">response</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">as_bytes</span><span style="color:#89DDFF;">()).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">flush</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>此时我们再次访问我们的地址，将不会得到报错信息，而是返回一个空白的页面，说明我们的页面请求已经得到了响应，那么接下来我们需要让我们的服务器能够返回真实的 web 页面：</p><p>我们编写一个 hello.html 页面，放在项目的根目录下：</p><div class="language-html"><button class="copy"></button><span class="lang">html</span><pre><code><span class="line"><span style="color:#89DDFF;">&lt;!</span><span style="color:#F07178;">DOCTYPE</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">html</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">html</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">lang</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">en</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">head</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">meta</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">charset</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">utf-8</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">title</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">Hello!</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">title</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">head</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">body</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">h1</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">Hello!</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">h1</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">p</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">Hi from Rust</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">p</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">body</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">html</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"></span></code></pre></div><p>之后在返回处理方法中读取我们刚刚编写页面的内容，构造成 TCP 请求的返回格式进行返回：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::{</span></span>
<span class="line"><span style="color:#FFCB6B;">    fs</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#FFCB6B;">    io</span><span style="color:#89DDFF;">::{</span><span style="color:#FFCB6B;">prelude</span><span style="color:#89DDFF;">::*,</span><span style="color:#FFCB6B;"> BufReader</span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#FFCB6B;">    net</span><span style="color:#89DDFF;">::{</span><span style="color:#FFCB6B;">TcpListener</span><span style="color:#89DDFF;">,</span><span style="color:#FFCB6B;"> TcpStream</span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#676E95;">// --snip--</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">handle_connection</span><span style="color:#89DDFF;">(</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> stream</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">TcpStream</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> buffer </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1024</span><span style="color:#89DDFF;">];</span></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">read</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> buffer</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> status_line </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">HTTP/1.1 200 OK</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> contents </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">fs</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">read_to_string</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">hello.html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> length </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> contents</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">len</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> response </span><span style="color:#89DDFF;">=</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#82AAFF;">format!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;{</span><span style="color:#C3E88D;">status_line</span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">\r\n</span><span style="color:#C3E88D;">Content-Length: </span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">length</span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">\r\n\r\n</span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">contents</span><span style="color:#89DDFF;">}&quot;</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">write_all</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">response</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">as_bytes</span><span style="color:#89DDFF;">()).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">flush</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>当然我们的服务器不可能只返回一个页面，对于不同路径的 TCP 请求，我们需要为他们返回不同的页面，所以我们做了一个模式匹配，如果是请求的主页我们返回一个页面，如果请求其他页面，我们返回一个 404 页面表示找不到</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">handle_connection</span><span style="color:#89DDFF;">(</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> stream</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">TcpStream</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> buffer </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1024</span><span style="color:#89DDFF;">];</span></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">read</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> buffer</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> get </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">b</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">GET / HTTP/1.1</span><span style="color:#A6ACCD;">\r\n</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">status_line</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> filename</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">if</span><span style="color:#A6ACCD;"> buffer</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">starts_with</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">get</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">HTTP/1.1 200 OK</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">index.html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">else</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">HTTP/1.1 404 NOT FOUND</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">404.html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> contents </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">fs</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">read_to_string</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">filename</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> response </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">format!</span><span style="color:#89DDFF;">(</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">&quot;{}</span><span style="color:#A6ACCD;">\r\n</span><span style="color:#C3E88D;">Content-Length: </span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">\r\n\r\n</span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        status_line</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        contents</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">len</span><span style="color:#89DDFF;">(),</span></span>
<span class="line"><span style="color:#A6ACCD;">        contents</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">write_all</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">response</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">as_bytes</span><span style="color:#89DDFF;">()).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">flush</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><h2 id="多线程的web-server" tabindex="-1">多线程的web server <a class="header-anchor" href="#多线程的web-server" aria-hidden="true">#</a></h2><p>之前搭建的服务器，一次只能处理一个请求，如果我们遇到多个请求的情况，只有当上一个请求处理完毕才能处理下一个请求，当一个请求时间很长的时候，会极大影响整体的性能，比如我们构造一个 sleep 路径，它在阻塞 5 秒钟后才返回，那么整个服务器的所有请求都会阻塞：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">fs</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">io</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">prelude</span><span style="color:#89DDFF;">::*;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">net</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">TcpListener</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">net</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">TcpStream</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">thread</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">time</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Duration</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">handle_connection</span><span style="color:#89DDFF;">(</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> stream</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">TcpStream</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> buffer </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1024</span><span style="color:#89DDFF;">];</span></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">read</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> buffer</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> get </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">b</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">GET / HTTP/1.1</span><span style="color:#A6ACCD;">\r\n</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> sleep </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">b</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">GET /sleep HTTP/1.1</span><span style="color:#A6ACCD;">\r\n</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">status_line</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> filename</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">if</span><span style="color:#A6ACCD;"> buffer</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">starts_with</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">get</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">HTTP/1.1 200 OK</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">index.html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">else</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">if</span><span style="color:#A6ACCD;"> buffer</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">starts_with</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">sleep</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">thread</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">sleep</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Duration</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">from_secs</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">HTTP/1.1 200 OK</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">index.html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">else</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">HTTP/1.1 404 NOT FOUND</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">404.html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> contents </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">fs</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">read_to_string</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">filename</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> response </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">format!</span><span style="color:#89DDFF;">(</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">&quot;{}</span><span style="color:#A6ACCD;">\r\n</span><span style="color:#C3E88D;">Content-Length: </span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">\r\n\r\n</span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        status_line</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        contents</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">len</span><span style="color:#89DDFF;">(),</span></span>
<span class="line"><span style="color:#A6ACCD;">        contents</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">write_all</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">response</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">as_bytes</span><span style="color:#89DDFF;">()).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">flush</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>为了解决这个情况我们需要一个多线程的服务器，我们需要设计一个 <strong>线程池</strong>（<em>thread pool</em>）。当程序收到一个新任务，线程池中的一个线程会被分配任务，这个线程会离开并处理任务。其余的线程则可用于处理在第一个线程处理任务的同时处理其他接收到的任务。当第一个线程处理完任务时，它会返回空闲线程池中等待处理新任务。线程池允许我们并发处理连接，增加 server 的吞吐量。同时，为了保证我们的服务器 不被 Dos 攻击，我们需要限定我们线程的数量，所有我们的线程池应该在初始化的时候可以限定最大线程数，所以我们的线程池调用应该是这样的：</p><p>使用 <code>ThreadPool::new</code> 来创建一个新的线程池，它有一个可配置的线程数的参数，<code>pool.execute</code> 有着类似 <code>thread::spawn</code> 的接口，它获取一个线程池运行于每一个流的闭包。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> listener </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">TcpListener</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">bind</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">127.0.0.1:7878</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> pool </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">4</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> stream </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> listener</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">incoming</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> stream </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">        pool</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">execute</span><span style="color:#89DDFF;">(||</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#82AAFF;">handle_connection</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">stream</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">});</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>有了目标之后，我们就可以编写我们的 <code>ThreadPool</code> 程序，我们创建 <code>src/lib.rs</code> 文件，在其中创建我们的 <code>ThreadPool </code> ，它包含一个 new 函数以及一个 执行函数 <code>execute</code></p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">ThreadPool</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">execute</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">&gt;(&amp;</span><span style="color:#A6ACCD;">self</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> f</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">where</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">FnOnce</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Send</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#FFCB6B;">static</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>这里传入泛型如此约束的原因是，我们的 <code>execute</code> 函数参照了标准库的 <code>thread::spawn</code> 函数，它的定义如下：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">spawn</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">T</span><span style="color:#89DDFF;">&gt;(</span><span style="color:#A6ACCD;">f</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">JoinHandle</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">T</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">where</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">FnOnce</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">T</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Send</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#FFCB6B;">static</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">T</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Send</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#FFCB6B;">static</span><span style="color:#89DDFF;">,</span></span>
<span class="line"></span></code></pre></div><p>之后我们可以看到，<code>spawn</code> 返回一个 <code>JoinHandle</code> 类型的数据，所以我们也可以使用它来包裹我们的线程，我们在 <code>ThreadPool </code> 结构中定义 Vec 来存储我们的线程：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">thread</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    threads</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Vec</span><span style="color:#89DDFF;">&lt;</span><span style="color:#A6ACCD;">thread</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">JoinHandle</span><span style="color:#89DDFF;">&lt;()&gt;&gt;,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#676E95;">    // --snip--</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#82AAFF;">assert!</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size </span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> threads </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Vec</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">with_capacity</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> _ </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">size </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#676E95;">            // create some threads and store them in the vector</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> threads </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#676E95;">    // --snip--</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>此时我们的项目已经可以运行了，我们还没有实现我们的线程的具体内容，我们将要实现的行为是创建线程并稍后发送代码，所以我们需要在 <code>ThreadPool</code> 和线程间引入一个新数据类型来管理这种新行为，这个数据结构称为 <em>Worker</em>，每一个 <code>Worker</code> 会储存一个单独的 <code>JoinHandle&lt;()&gt;</code> 实例。接着会在 <code>Worker</code> 上实现一个方法，它会获取需要允许代码的闭包并将其发送给已经运行的线程执行。我们还会赋予每一个 worker <code>id</code>，这样就可以在日志和调试中区别线程池中的不同 worker。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">thread</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    workers</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Vec</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Worker</span><span style="color:#89DDFF;">&gt;,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#676E95;">    // --snip--</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#82AAFF;">assert!</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size </span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> workers </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Vec</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">with_capacity</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> id </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">size </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            workers</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">push</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Worker</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> workers </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#676E95;">    // --snip--</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    id</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">    thread</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">thread</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">JoinHandle</span><span style="color:#89DDFF;">&lt;()&gt;,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> thread </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">thread</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">spawn</span><span style="color:#89DDFF;">(||</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{});</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> id</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> thread </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>我们已经可以创建线程，但是之后我们需要将我们通过 <code>execute</code> 方法传递进来的方法放入我们的线程中，我们使用 <strong>信道</strong> —— 作为沟通工具，方案如下：</p><ol><li><code>ThreadPool</code> 会创建一个信道并充当发送者。</li><li>每个 <code>Worker</code> 将会充当接收者。</li><li>新建一个 <code>Job</code> 结构体来存放用于向信道中发送的闭包。</li><li><code>execute</code> 方法会在发送者发出期望执行的任务。</li><li>在线程中，<code>Worker</code> 会遍历接收者并执行任何接收到的任务。</li></ol><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::{</span><span style="color:#FFCB6B;">sync</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">mpsc</span><span style="color:#89DDFF;">,</span><span style="color:#FFCB6B;"> thread</span><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    workers</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Vec</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Worker</span><span style="color:#89DDFF;">&gt;,</span></span>
<span class="line"><span style="color:#A6ACCD;">    sender</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">mpsc</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Sender</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Job</span><span style="color:#89DDFF;">&gt;,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Job</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#676E95;">    // --snip--</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#82AAFF;">assert!</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size </span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">sender</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> receiver</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">mpsc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">channel</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> workers </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Vec</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">with_capacity</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> id </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">size </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            workers</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">push</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Worker</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> receiver</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> workers</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> sender </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#676E95;">    // --snip--</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;">// --snip--</span></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> receiver</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">mpsc</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Receiver</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Job</span><span style="color:#89DDFF;">&gt;)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> thread </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">thread</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">spawn</span><span style="color:#89DDFF;">(||</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            receiver</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">});</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> id</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> thread </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>但是上述的代码有一个问题，这段代码尝试将 <code>receiver</code> 传递给多个 <code>Worker</code> 实例。这是不行的，Rust 所提供的信道实现是多 <strong>生产者</strong>，单 <strong>消费者</strong> 的。为了在多个线程间共享所有权并允许线程修改其值，需要使用 <code>Arc&lt;Mutex&lt;T&gt;&gt;</code>。<code>Arc</code> 使得多个 worker 拥有接收端，而 <code>Mutex</code> 则确保一次只有一个 worker 能从接收端得到任务：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::{</span></span>
<span class="line"><span style="color:#FFCB6B;">    sync</span><span style="color:#89DDFF;">::{</span><span style="color:#FFCB6B;">mpsc</span><span style="color:#89DDFF;">,</span><span style="color:#FFCB6B;"> Arc</span><span style="color:#89DDFF;">,</span><span style="color:#FFCB6B;"> Mutex</span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#FFCB6B;">    thread</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#676E95;">// --snip--</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#676E95;">    // --snip--</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#82AAFF;">assert!</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size </span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">sender</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> receiver</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">mpsc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">channel</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> receiver </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Arc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Mutex</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">receiver</span><span style="color:#89DDFF;">));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> workers </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Vec</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">with_capacity</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> id </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">size </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            workers</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">push</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Worker</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Arc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">clone</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">receiver</span><span style="color:#89DDFF;">)));</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> workers</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> sender </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;">    // --snip--</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;">// --snip--</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> receiver</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Arc</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Mutex</span><span style="color:#89DDFF;">&lt;</span><span style="color:#A6ACCD;">mpsc</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Receiver</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Job</span><span style="color:#89DDFF;">&gt;&gt;&gt;)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#676E95;">        // --snip--</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>最后我们需要实现 <code>ThreadPool</code> 上的 <code>execute</code> 方法，它将接收到的方法传递到线程中，并且执行它。而在 worker 中，传递给 <code>thread::spawn</code> 的闭包仍然还只是 <strong>引用</strong> 了信道的接收端。我们需要闭包一直循环，向信道的接收端请求任务，并在得到任务时执行他们。</p><p>这里调用了 <code>lock</code> 来获取互斥器，如果互斥器处于一种叫做 <strong>被污染</strong>（<em>poisoned</em>）的状态时获取锁可能会失败，这可能发生于其他线程在持有锁时 panic 了且没有释放锁。如果锁定了互斥器，接着调用 <code>recv</code> 从信道中接收 <code>Job</code>，调用 <code>recv</code> 会阻塞当前线程，所以如果还没有任务，其会等待直到有可用的任务。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#C792EA;">type</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Job</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Box</span><span style="color:#89DDFF;">&lt;</span><span style="color:#F78C6C;">dyn</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">FnOnce</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Send</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#FFCB6B;">static</span><span style="color:#89DDFF;">&gt;;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#676E95;">    // --snip--</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">execute</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">&gt;(&amp;</span><span style="color:#A6ACCD;">self</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> f</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">where</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">FnOnce</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Send</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#FFCB6B;">static</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> job </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Box</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">f</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        self</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sender</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">send</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">job</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;">// --snip--</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> receiver</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Arc</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Mutex</span><span style="color:#89DDFF;">&lt;</span><span style="color:#A6ACCD;">mpsc</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Receiver</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Job</span><span style="color:#89DDFF;">&gt;&gt;&gt;)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> thread </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">thread</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">spawn</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">move</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">||</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">loop</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> job </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> receiver</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">lock</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">recv</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Worker </span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">id</span><span style="color:#89DDFF;">}</span><span style="color:#C3E88D;"> got a job; executing.</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#82AAFF;">job</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">});</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> id</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> thread </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"></span></code></pre></div><h2 id="停机与清理" tabindex="-1">停机与清理 <a class="header-anchor" href="#停机与清理" aria-hidden="true">#</a></h2><p>之前编写代码已经可以完整运行了，但是面临两个问题，一个是我们不能停止我们的服务器，只能使用命令行的强制停止程序命令，并且我们的服务器并没有清理所有的内容，所以我们需要继续完善我们的服务器：</p><p>首先，我们为线程池实现 <code>Drop</code>。当线程池被丢弃时，应该 join 所有线程以确保他们完成其操作。这里首先遍历线程池中的每个 <code>workers</code>。对于每一个线程，会打印出说明信息表明此特定 worker 正在关闭，接着在 worker 线程上调用 <code>join</code>。如果 <code>join</code> 调用失败，通过 <code>unwrap</code> 使得 panic 并进行不优雅的关闭。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Drop</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">drop</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> self</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> worker </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> self</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">workers </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Shutting down worker </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> worker</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">            worker</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">thread</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">join</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>因为目前只有每一个 <code>worker</code> 的可变借用，而 <code>join</code> 需要获取其参数的所有权。如果 <code>Worker</code> 存放的是 <code>Option&lt;thread::JoinHandle&lt;()&gt;</code>，就可以在 <code>Option</code> 上调用 <code>take</code> 方法将值从 <code>Some</code> 成员中移动出来而对 <code>None</code> 成员不做处理。换句话说，正在运行的 <code>Worker</code> 的 <code>thread</code> 将是 <code>Some</code> 成员值，而当需要清理 worker 时，将 <code>Some</code> 替换为 <code>None</code>，这样 worker 就没有可以运行的线程了。所以我们需要为此需要更新 <code>Worker</code> 的定义为如下：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    id</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">    thread</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Option</span><span style="color:#89DDFF;">&lt;</span><span style="color:#A6ACCD;">thread</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">JoinHandle</span><span style="color:#89DDFF;">&lt;()&gt;&gt;,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>对此，当新建 <code>Worker</code> 时需要将 <code>thread</code> 值封装进 <code>Some</code>。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> receiver</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Arc</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Mutex</span><span style="color:#89DDFF;">&lt;</span><span style="color:#A6ACCD;">mpsc</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Receiver</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Job</span><span style="color:#89DDFF;">&gt;&gt;&gt;)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#676E95;">        // --snip--</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            id</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            thread</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Some</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">thread</span><span style="color:#89DDFF;">),</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Drop</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">drop</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> self</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> worker </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> self</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">workers </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Shutting down worker </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> worker</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#89DDFF;">if</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Some</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">thread</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> worker</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">thread</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">take</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">                thread</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">join</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>现在程序可以通过编译了，但是存在的问题是： <code>Worker</code> 中分配的线程所运行的闭包中的逻辑：调用 <code>join</code> 并不会关闭线程，因为他们一直 <code>loop</code> 来寻找任务。如果采用这个实现来尝试丢弃 <code>ThreadPool</code>，则主线程会永远阻塞在等待第一个线程结束上。</p><p>所以我们需要修改 <code>ThreadPool</code> 的 <code>drop</code> 实现并修改 <code>Worker</code> 循环。我们需要在等待线程结束前显式丢弃 <code>sender</code></p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    workers</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Vec</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Worker</span><span style="color:#89DDFF;">&gt;,</span></span>
<span class="line"><span style="color:#A6ACCD;">    sender</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Option</span><span style="color:#89DDFF;">&lt;</span><span style="color:#A6ACCD;">mpsc</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Sender</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Job</span><span style="color:#89DDFF;">&gt;&gt;,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#676E95;">// --snip--</span></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#676E95;">        // --snip--</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            workers</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            sender</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Some</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">sender</span><span style="color:#89DDFF;">),</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">execute</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">&gt;(&amp;</span><span style="color:#A6ACCD;">self</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> f</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">where</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">FnOnce</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Send</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#FFCB6B;">static</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> job </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Box</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">f</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        self</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sender</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">as_ref</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">send</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">job</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Drop</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">drop</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> self</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#82AAFF;">drop</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">self</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sender</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">take</span><span style="color:#89DDFF;">());</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> worker </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> self</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">workers </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Shutting down worker </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> worker</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#89DDFF;">if</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Some</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">thread</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> worker</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">thread</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">take</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">                thread</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">join</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>丢弃 <code>sender</code> 会关闭信道，这表明不会有更多的消息被发送，这时 worker 中的无限循环中的所有 <code>recv</code> 调用都会返回错误。我们修改 <code>Worker</code> 循环在这种情况下优雅地退出，这意味着当 <code>ThreadPool</code> 的 <code>drop</code> 实现调用 <code>join</code> 时线程会结束。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> receiver</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Arc</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Mutex</span><span style="color:#89DDFF;">&lt;</span><span style="color:#A6ACCD;">mpsc</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Receiver</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Job</span><span style="color:#89DDFF;">&gt;&gt;&gt;)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> thread </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">thread</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">spawn</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">move</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">||</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">loop</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> message </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> receiver</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">lock</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">recv</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#89DDFF;">match</span><span style="color:#A6ACCD;"> message </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">                </span><span style="color:#FFCB6B;">Ok</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">job</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">                    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Worker </span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">id</span><span style="color:#89DDFF;">}</span><span style="color:#C3E88D;"> got a job; executing.</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">                    </span><span style="color:#82AAFF;">job</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">                </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">                </span><span style="color:#FFCB6B;">Err</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">_</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">                    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Worker </span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">id</span><span style="color:#89DDFF;">}</span><span style="color:#C3E88D;"> disconnected; shutting down.</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">                    </span><span style="color:#89DDFF;">break</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">                </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">});</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            id</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            thread</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Some</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">thread</span><span style="color:#89DDFF;">),</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>修改 <code>main</code> 函数，可以让收到指定数量的请求后停机：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> listener </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">TcpListener</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">bind</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">127.0.0.1:7878</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> pool </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">4</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> stream </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> listener</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">incoming</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">take</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">2</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> stream </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        pool</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">execute</span><span style="color:#89DDFF;">(||</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#82AAFF;">handle_connection</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">stream</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">});</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Shutting down.</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>至此一个完整的小型 web 服务器搭建完毕，完整的代码如下：</p><p>文件名：src/main.rs</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> hello</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#89DDFF;">;</span><span style="color:#676E95;">//改成你hello的项目名字</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">fs</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">io</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">prelude</span><span style="color:#89DDFF;">::*;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">net</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">TcpListener</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">net</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">TcpStream</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">thread</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">time</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Duration</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> listener </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">TcpListener</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">bind</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">127.0.0.1:7878</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> pool </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">4</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> stream </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> listener</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">incoming</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">take</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">2</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> stream </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        pool</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">execute</span><span style="color:#89DDFF;">(||</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#82AAFF;">handle_connection</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">stream</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">});</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Shutting down.</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">handle_connection</span><span style="color:#89DDFF;">(</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> stream</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">TcpStream</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> buffer </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1024</span><span style="color:#89DDFF;">];</span></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">read</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> buffer</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> get </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">b</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">GET / HTTP/1.1</span><span style="color:#A6ACCD;">\r\n</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> sleep </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">b</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">GET /sleep HTTP/1.1</span><span style="color:#A6ACCD;">\r\n</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">status_line</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> filename</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">if</span><span style="color:#A6ACCD;"> buffer</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">starts_with</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">get</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">HTTP/1.1 200 OK</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">hello.html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">else</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">if</span><span style="color:#A6ACCD;"> buffer</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">starts_with</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">sleep</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">thread</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">sleep</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Duration</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">from_secs</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">HTTP/1.1 200 OK</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">hello.html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">else</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">HTTP/1.1 404 NOT FOUND</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">404.html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> contents </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">fs</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">read_to_string</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">filename</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> response </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">format!</span><span style="color:#89DDFF;">(</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">&quot;{}</span><span style="color:#A6ACCD;">\r\n</span><span style="color:#C3E88D;">Content-Length: </span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">\r\n\r\n</span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        status_line</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        contents</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">len</span><span style="color:#89DDFF;">(),</span></span>
<span class="line"><span style="color:#A6ACCD;">        contents</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">write_all</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">response</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">as_bytes</span><span style="color:#89DDFF;">()).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">    stream</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">flush</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>文件名：src/lib.rs：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::{</span></span>
<span class="line"><span style="color:#FFCB6B;">    sync</span><span style="color:#89DDFF;">::{</span><span style="color:#FFCB6B;">mpsc</span><span style="color:#89DDFF;">,</span><span style="color:#FFCB6B;"> Arc</span><span style="color:#89DDFF;">,</span><span style="color:#FFCB6B;"> Mutex</span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#FFCB6B;">    thread</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    workers</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Vec</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Worker</span><span style="color:#89DDFF;">&gt;,</span></span>
<span class="line"><span style="color:#A6ACCD;">    sender</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Option</span><span style="color:#89DDFF;">&lt;</span><span style="color:#A6ACCD;">mpsc</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Sender</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Job</span><span style="color:#89DDFF;">&gt;&gt;,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">type</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Job</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Box</span><span style="color:#89DDFF;">&lt;</span><span style="color:#F78C6C;">dyn</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">FnOnce</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Send</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#FFCB6B;">static</span><span style="color:#89DDFF;">&gt;;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#676E95;">    /// Create a new ThreadPool.</span></span>
<span class="line"><span style="color:#676E95;">    ///</span></span>
<span class="line"><span style="color:#676E95;">    /// The size is the number of threads in the pool.</span></span>
<span class="line"><span style="color:#676E95;">    ///</span></span>
<span class="line"><span style="color:#676E95;">    /// # Panics</span></span>
<span class="line"><span style="color:#676E95;">    ///</span></span>
<span class="line"><span style="color:#676E95;">    /// The `new` function will panic if the size is zero.</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#82AAFF;">assert!</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size </span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">sender</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> receiver</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">mpsc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">channel</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> receiver </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Arc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Mutex</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">receiver</span><span style="color:#89DDFF;">));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> workers </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Vec</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">with_capacity</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">size</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> id </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">size </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            workers</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">push</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Worker</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Arc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">clone</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">receiver</span><span style="color:#89DDFF;">)));</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            workers</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            sender</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Some</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">sender</span><span style="color:#89DDFF;">),</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">pub</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">execute</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">&gt;(&amp;</span><span style="color:#A6ACCD;">self</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> f</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">where</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">F</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">FnOnce</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Send</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#FFCB6B;">static</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> job </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Box</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">f</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        self</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sender</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">as_ref</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">send</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">job</span><span style="color:#89DDFF;">).</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Drop</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ThreadPool</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">drop</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> self</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#82AAFF;">drop</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">self</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sender</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">take</span><span style="color:#89DDFF;">());</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> worker </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> self</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">workers </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Shutting down worker </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> worker</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#89DDFF;">if</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Some</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">thread</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> worker</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">thread</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">take</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">                thread</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">join</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    id</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">    thread</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Option</span><span style="color:#89DDFF;">&lt;</span><span style="color:#A6ACCD;">thread</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">JoinHandle</span><span style="color:#89DDFF;">&lt;()&gt;&gt;,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">usize</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> receiver</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Arc</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Mutex</span><span style="color:#89DDFF;">&lt;</span><span style="color:#A6ACCD;">mpsc</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Receiver</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Job</span><span style="color:#89DDFF;">&gt;&gt;&gt;)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> thread </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">thread</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">spawn</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">move</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">||</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">loop</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> message </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> receiver</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">lock</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">unwrap</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">recv</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#89DDFF;">match</span><span style="color:#A6ACCD;"> message </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">                </span><span style="color:#FFCB6B;">Ok</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">job</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">                    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Worker </span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">id</span><span style="color:#89DDFF;">}</span><span style="color:#C3E88D;"> got a job; executing.</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">                    </span><span style="color:#82AAFF;">job</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">                </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">                </span><span style="color:#FFCB6B;">Err</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">_</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">                    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Worker </span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">id</span><span style="color:#89DDFF;">}</span><span style="color:#C3E88D;"> disconnected; shutting down.</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">                    </span><span style="color:#89DDFF;">break</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">                </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">});</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">Worker</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            id</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            thread</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Some</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">thread</span><span style="color:#89DDFF;">),</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>这里还有很多可以做的事！如果你希望继续增强这个项目，如下是一些点子：</p><ul><li>为 <code>ThreadPool</code> 和其公有方法增加更多文档</li><li>为库的功能增加测试</li><li>将 <code>unwrap</code> 调用改为更健壮的错误处理</li><li>使用 <code>ThreadPool</code> 进行其他不同于处理网络请求的任务</li><li>在 <a href="https://crates.io/" target="_blank" rel="noreferrer">crates.io</a> 上寻找一个线程池 crate 并使用它实现一个类似的 web server，将其 API 和鲁棒性与我们的实现做对比</li></ul></div></div></main><!--[--><!--]--><footer class="VPDocFooter" data-v-37ebe389 data-v-a54a85bd><!----><div class="prev-next" data-v-a54a85bd><div class="pager" data-v-a54a85bd><a class="pager-link prev" href="/articles/rust/15.%E9%AB%98%E7%BA%A7%E7%89%B9%E6%80%A7.html" data-v-a54a85bd><span class="desc" data-v-a54a85bd>Previous page</span><span class="title" data-v-a54a85bd>15.高级特性</span></a></div><div class="has-prev pager" data-v-a54a85bd><a class="pager-link next" href="/articles/rust/17.rust%E5%BC%82%E6%AD%A5%E7%BC%96%E7%A8%8B.html" data-v-a54a85bd><span class="desc" data-v-a54a85bd>Next page</span><span class="title" data-v-a54a85bd>17.rust异步编程</span></a></div></div></footer><!--[--><!--]--></div></div></div></div></div><!----><!--[--><!--]--></div></div>
    <script>__VP_HASH_MAP__ = JSON.parse("{\"articles_basic-bitdance_class01-html.md\":\"ff4ff513\",\"articles_basic-bitdance_class02-css.md\":\"a702a9f8\",\"articles_basic-bitdance_class03-js.md\":\"0cf4e640\",\"articles_basic-bitdance_class04-typescript.md\":\"6eb8a62e\",\"articles_basic-bitdance_class05-http.md\":\"cb129388\",\"articles_basic-bitdance_class06-react.md\":\"a4c71f1a\",\"articles_basic-bitdance_class07-node.md\":\"7925a6b7\",\"articles_basic-bitdance_class08-next.js.md\":\"893eef63\",\"articles_basic-bitdance_class08.5-开发技巧.md\":\"e6d7e150\",\"articles_basic-bitdance_class09-跨端技术.md\":\"25156c46\",\"articles_basic-bitdance_class10-调试.md\":\"f07f60c2\",\"articles_basic-bitdance_class11-安全.md\":\"3c992463\",\"articles_basic-bitdance_class12-监控sdk.md\":\"35ef00f1\",\"articles_basic-bitdance_class13-webpack.md\":\"70e5acc7\",\"articles_basic-bitdance_class14-vite.md\":\"9cfa31e3\",\"articles_basic-bitdance_class15-可视化.md\":\"4c9a2433\",\"articles_basic_index.md\":\"5c1f50b5\",\"articles_electron_index.md\":\"acb5a448\",\"articles_electron_测试.md\":\"5404a20a\",\"articles_mini_index.md\":\"9af79c7b\",\"articles_other_vitepress_01.vitepress的搭建.md\":\"b8deb5b2\",\"articles_other_vitepress_02.vitepress的部署.md\":\"cf416a09\",\"articles_other_vitepress_03.vitepress自动生成目录.md\":\"0dd6d021\",\"articles_other_vitepress_04.vitepress引入vue组件.md\":\"46052034\",\"articles_react_index.md\":\"ec69e04d\",\"articles_react_source code_01.react的架构.md\":\"f4181c9b\",\"articles_rust_01.基础入门.md\":\"af35ebe7\",\"articles_rust_02.基础语法.md\":\"eba033ca\",\"articles_rust_03.指针与内存分配.md\":\"b6d4df62\",\"articles_rust_04.程序结构和异常处理.md\":\"07567152\",\"articles_rust_05.数据结构与泛型.md\":\"6d5c530d\",\"articles_rust_06.trait与生命周期.md\":\"5e57b7aa\",\"articles_rust_07.编写测试.md\":\"bd7d6015\",\"articles_rust_08.构建命令行程序.md\":\"a295a848\",\"articles_rust_09.闭包与迭代器.md\":\"cf79a80f\",\"articles_rust_10.发布项目.md\":\"9e4f6be1\",\"articles_rust_11.智能指针.md\":\"48ecbccd\",\"articles_rust_12.并发.md\":\"62f8f67e\",\"articles_rust_13.面向对象.md\":\"a8519b1a\",\"articles_rust_14.不安全rust.md\":\"a079df80\",\"articles_rust_15.高级特性.md\":\"2b09c61c\",\"articles_rust_16.手写web服务器和线程池.md\":\"97f59e40\",\"articles_rust_17.rust异步编程.md\":\"e26606a3\",\"articles_rustweb_01.简单 server.md\":\"6c2ab750\",\"articles_rustweb_02.actix.md\":\"048a9c59\",\"articles_rustweb_03.连接数据库.md\":\"5ccb794e\",\"articles_rustweb_04.错误处理.md\":\"bd3759f6\",\"articles_rustweb_05.完整项目重构.md\":\"d160a226\",\"articles_rustweb_06.服务器端web应用.md\":\"cdc4f4ca\",\"articles_rustweb_07.webassembly.md\":\"0f1bc773\",\"articles_rustweb_08.发布.md\":\"d4792485\",\"articles_vue_index.md\":\"5ded6ffa\",\"articles_vue组件库_vue3组件库项目学习笔记（1）：基础搭建.md\":\"23c5186c\",\"articles_vue组件库_vue3组件库项目学习笔记（2）：开发一个组件.md\":\"fdd9e315\",\"articles_vue组件库_vue3组件库项目学习笔记（3）：测试你的组件.md\":\"7a02b7b2\",\"articles_vue组件库_vue3组件库项目学习笔记（4）：发布你的组件.md\":\"e0b3816e\",\"articles_vue组件库_vue3组件库项目学习笔记（5）：配置编码规范.md\":\"291e9a8e\",\"articles_vue组件库_vue3组件库项目学习笔记（6）：发布组件文档.md\":\"3fa49d31\",\"articles_vue组件库_vue3组件库项目学习笔记（7）：正式开发问题拾遗.md\":\"85204ad9\",\"articles_vue组件库_vue3组件库项目学习笔记（8）：git协作.md\":\"ab61313a\",\"articles_web3d_index.md\":\"a52fc82e\",\"index.md\":\"de494fc0\",\"intent_index.md\":\"82efde64\",\"leetcode_leet_code题解_47. 全排列 ii.md\":\"c8680b3d\",\"leetcode_leet_code题解_49. 字母异位词分组.md\":\"e37b3116\",\"leetcode_leet_code题解_55. 跳跃游戏.md\":\"29658916\",\"leetcode_leet_code题解_56. 合并区间.md\":\"8f16bd71\",\"public_draco_readme.md\":\"5da4c955\"}")</script>
    <script type="module" async src="/assets/app.75d9ecf2.js"></script>
    
  </body>
</html>